#!/usr/local/bin/php
<?
/**
 * place following in board_config.php
 * $board_config['developer'] = 'nana';
 * $board_config['developer_db_dir'] = '/var/www/html/niced/application/developer_db';
*/
class NICED_InstallDevDB
{
    private $developer = NULL;
    private $mysqlDsn  = array();
    private $loginUser = NULL;
    private $execCmd       = NULL;
    private $developerDBDir = NULL;

    private $opts = array(
        "verbose"       => true,
        "showCommand"   => false,
        "haltOnError"   => false,
        "overwriteDB"   => false,
    );

    private $binPaths = array(
        "cat"   => NULL, 
        "sed"   => NULL, 
        "mysql" => NULL,
    );

    public function __construct()
    {
        $this->init();
        $this->checkUserAndDeveloper();
        $this->buildExecCmd();
    }

    private function init()
    {
        $this->initMysqlDsn();
        $this->initDeveloper();
        $this->initLoginUser();
        $this->initBinPath();
        $this->loadOpt();
    }

    private function initLoginUser()
    {
        //$this->loginUser = posix_getlogin();
        $cmd = "whoami";
        $this->loginUser = $this->executeOsCmd($cmd);
    }

    private function initMysqlDsn()
    {
        $this->mysqlDsn = array(
            "host" => "127.0.0.1",
            "port" => "3306",
            "user" => "root",
            "pass" => "",
        );
    }

    private function initDeveloper()
    {
        $this->developer = SC::get('board_config.developer');

        if(!$this->developer) 
        {
            throw new Exception("No developer defined in board_config");
        }

        $this->developerDBDir = SC::get('board_config.developer_db_dir');

        if(!$this->developerDBDir) 
        {
            throw new Exception("No developer db dir defined in board_config");
        }
    }
    
    private function initBinPath()
    {
        foreach ($this->binPaths as $k => $v)
        {
            $fh = popen("which ".$k, "r");
            $rt = trim(fread($fh, 128));

            if (strlen($rt) == 0) 
            {
                throw new Exception($k." not found in ur operation system\n");
            } 
            else
            {
                $this->binPaths[$k] = $rt;
            }
        }
    }

    private function executeOsCmd($cmd)
    {
        $fh = popen($cmd, "r");
        $rt = trim(fread($fh, 128));

        if (strlen($rt) == 0) 
        {
            throw new Exception("execute os cmd ".$cmd.", os return is ".$rt);
        } 
        pclose($fh);

        return $rt;
    }

    private function checkUserAndDeveloper()
    {
        if($this->loginUser != $this->developer && !$this->opts["overwriteDB"])
        {
            throw new Exception( "initializing database ".$this->developer." that not be urs");
        }
    }

    public function run()
    {
        $this->buildExecCmd();
        $this->executeSQL();
    }

    private function executeSQL()
    {
        //should execute structure sql first
        $this->executeStructureSQL();
        $this->executeDataSQL();
    }

    private function executeStructureSQL()
    {
        $this->executeSQLFileByDir(rtrim($this->developerDBDir,DS).DS."structure");
    }

    private function executeDataSQL()
    {
        $dir = rtrim($this->developerDBDir, DS).DS."data"; 
        $dirs = Util::getDirFiles($dir, "dir");

        foreach ($dirs as $d)
        {
            if ("." != substr(basename($d), 0, 1))
            {
                $this->executeSQLFileByDir($d);
            }
        }
    }

    private function executeSQLFileByDir($dir)
    {
        $files = Util::getDirFiles($dir);

        if ($files && is_array($files))
        {
            $cmd = $this->execCmd;
            foreach ($files as $file)
            {
                $command = sprintf($cmd, $file);
                $exit_code = 0;
                //exec($command, $ret, $exit_code);
                echo $command."\n";
                $h = popen($command, "r");
                $ret = fread($h, 1024);
                echo $ret."\n";
                pclose($h);

                //if ($exit_code && $this->opts["haltOnError"]) 
                //{
                //    throw new Exception("failure when execute $file:\n$command\n");
                //}
            }
        }
    }

    private function buildExecCmd()
    {
        $bin_paths = $this->binPaths;
        $mysql_dsn = $this->mysqlDsn;
        //$this->execCmd = $bin_paths["cat"]." %s | ".$bin_paths["sed"]." s/{developer}/".$this->developer."/g | ".$bin_paths["mysql"]." -u".$mysql_dsn["user"]." -p"." -h".$mysql_dsn["host"]." -P".$mysql_dsn["port"];

        $this->execCmd = $bin_paths["cat"]." %s | ".$bin_paths["sed"]." s/{developer}/".$this->developer."/g | ".$bin_paths["mysql"]." -u".$mysql_dsn["user"]." -p".$mysql_dsn["pass"]." -h".$mysql_dsn["host"]." -P".$mysql_dsn["port"];
        //$this->execCmd = $bin_paths["cat"]." %s | ".$bin_paths["sed"]." s/{developer}/".$this->developer."/g >> abc.sql";
    }

    private function loadOpt()
    {
        $argv = $_SERVER["argv"];
        $opts = &$this->opts;

        foreach ($argv as $arg)
        {
            switch($arg)
            {
                case '--verbose':
                case '-v':
                {
                  $opts["verbose"] = true; 
                  break;
                }
                case '--show-command':
                case '-s':
                {
                  $opts["showCommand"] = true; 
                  break;
                }
                case '-H':
                case '--halt-on-error':
                {
                  $opts["haltOnError"] = true; 
                  break;
                }
                case '--force':
                {
                  $opts["overwriteDB"] = true; 
                  break;
                }
            }
        }
    }

}//end class

function main()
{
    echo "begin init developer db!\n";
    date_default_timezone_set("Asia/Shanghai");
    $start = microtime(true);

    $ds = DIRECTORY_SEPARATOR; 
    $base = dirname(dirname(dirname(__FILE__)));
    require_once($base.$ds."application".$ds."include".$ds."global.inc.php");
    require_once(dirname(dirname(dirname(__FILE__))).$ds."system".$ds."core".$ds."application.php");
    
    NICED_Application::init();

    $niced_install  = new NICED_InstallDevDB();
    $niced_install->run();

    echo "done!\n";
}

main();
